using System;
using System.Collections.Generic;
using System.Text;
using NBusiness.Query;

namespace NBusiness.Data.Providers.SqlServer.Query
{
    public abstract class SqlEvaluatable : IEvaluatable
    {
        #region IEvaluatable Members

        public IExpression Equal(object evaluatable)
        {
            return new SqlEqual(this, Coerce(evaluatable));
        }

        public IExpression NotEqual(object evaluatable)
        {
            return new SqlEqual(this, Coerce(evaluatable), true);
        }

        public IExpression GreaterThan(object evaluatable)
        {
            return new SqlGreaterThan(this, Coerce(evaluatable));
        }

        public IExpression GreaterThanOrEqual(object evaluatable)
        {
            return new SqlGreaterThan(this, Coerce(evaluatable), true);
        }

        public IExpression LessThan(object evaluatable)
        {
            return new SqlLessThan(this, Coerce(evaluatable));
        }

        public IExpression LessThanOrEqual(object evaluatable)
        {
            return new SqlLessThan(this, Coerce(evaluatable), true);
        }

        public IExpression Like(object evaluatable)
        {
            return new SqlLike(this, Coerce(evaluatable));
        }

        public IExpression NotLike(object evaluatable)
        {
            return new SqlLike(this, Coerce(evaluatable), true);
        }

        public IExpression In(object evaluatable)
        {
            return new SqlIn(this, Coerce(evaluatable));
        }

        public IExpression NotIn(object evaluatable)
        {
            return new SqlIn(this, Coerce(evaluatable), true);
        }

        public IExpression Is(object evaluatable)
        {
            return new SqlIs(this, Coerce(evaluatable));
        }

        public IExpression IsNot(object evaluatable)
        {
            return new SqlIs(this, Coerce(evaluatable), true);
        }

        #endregion

        #region IRelationalElement Members

        public abstract string ToSql();

        public abstract string ToSql(IQueryContext context);

        #endregion
        
        #region Operator overloads
        #region Greater Than
        public static SqlBoolean operator >(SqlEvaluatable column, object value)
        {
            return column.GreaterThan(Coerce(value)) as SqlBoolean;
        }
        public static SqlBoolean operator >=(SqlEvaluatable column, object value)
        {
            return column.GreaterThanOrEqual(Coerce(value)) as SqlBoolean;
        }
        #endregion

        #region Less Than
        public static SqlBoolean operator <(SqlEvaluatable column, object value)
        {
            return column.LessThan(Coerce(value)) as SqlBoolean;
        }
        public static SqlBoolean operator <=(SqlEvaluatable column, object value)
        {
            return column.LessThanOrEqual(Coerce(value)) as SqlBoolean;
        }
        #endregion

        #region Equality
        public static SqlEqual operator ==(SqlEvaluatable column, object value)
        {
            return column.Equal(Coerce(value)) as SqlEqual;
        }

        public static SqlEqual operator !=(SqlEvaluatable column, object value)
        {
            return column.NotEqual(Coerce(value)) as SqlEqual;
        }
        #endregion

        public static IEvaluatable Coerce(object value)
        {
            IEvaluatable right = null;
            if (value is IEvaluatable)
                right = value as IEvaluatable;
            else if (value is string && !string.IsNullOrEmpty((string)value) && ((string)value).StartsWith("@"))
                right = new SqlParameter((string)value);
            else
                right = new SqlPrimitive(value);

            return right;
        }
        #endregion        
    }
}
